#!/usr/bin/python3
# -*- coding: utf-8 -*-
'''
@Author: Phoenix
@Date: 2020-08-04 23:33:35
'''

import os
from datetime import datetime
from shutil import copy, rmtree
from sys import exit

import main
from modules.utils import *

# VX ACE引擎默认文本库
RPGVXACE_DEFAULT_LIBRARY = 'rpgvxace_default_library.json'

TYPE_COMMONEVENTS = 'CommonEvents'
TYPE_SYSTEM = 'System'

# 要扫描的属性参数
KEY_NAME = '@name'
KEY_DESCRIPTION = '@description'
KEY_EVENTS = '@events'
KEY_PAGES = '@pages'
KEY_LIST = '@list'
KEY_CODE = '@code'
KEY_PARAMETERS = '@parameters'
# -------- Actors.json --------
KEY_NICKNAME = '@nickname'
# -------- States.json --------
KEY_MESSAGE1 = '@message1'
KEY_MESSAGE2 = '@message2'
KEY_MESSAGE3 = '@message3'
KEY_MESSAGE4 = '@message4'
# -------- System.json --------
KEY_ELEMENTS = '@elements'
KEY_TERMS = '@terms'
KEY_PARAMS = '@params'
KEY_ETYPES = '@etypes'
KEY_COMMANDS = '@commands'
KEY_BASIC = '@basic'
KEY_SKILL_TYPES = '@skill_types'
KEY_WEAPON_TYPES = '@weapon_types'
KEY_ARMOR_TYPES = '@armor_types'
KEY_CURRENCY_UNIT = '@currency_unit'
# -------- Mapxxx.json --------
KEY_DISPLAY_NAME = '@display_name'

# 缓存文本
_game_txt_cache = {}
# 默认文本
_game_txt_library = {}


def walk_file(_type: str):
    '''
    遍历文件夹内所有内容
    '''

    if not os.path.exists(RPGM_INPUT_ABSPATH):
        os.makedirs(RPGM_INPUT_ABSPATH)
    if os.path.exists(RPGM_OUTPUT_ABSPATH):
        rmtree(RPGM_OUTPUT_ABSPATH)
    os.makedirs(RPGM_OUTPUT_ABSPATH)

    if not _read_game_txt(_type):
        return

    # 遍历所有文件和目录，筛选出需要的json文件进行处理
    for root, dirs, files in os.walk(RPGM_INPUT_ABSPATH, topdown=False):

        # 新文件目录
        relative_path = os.path.relpath(root, RPGM_INPUT_ABSPATH)
        new_path = (
            RPGM_OUTPUT_ABSPATH
            if relative_path == '.'
            else os.path.join(RPGM_OUTPUT_ABSPATH, relative_path)
        )
        # 若新目录不存在，创建它
        if not os.path.exists(new_path):
            os.makedirs(new_path)

        for json_file in files:
            if not json_file.endswith('.json'):
                continue

            # 如果当前json文件不在白名单内，且不符合Map地图文件，则跳过它
            if not json_file[:-5] in GLOBAL_DATA[
                'rpg_white_list'
            ] and not PATTERN_MAP.match(json_file[:-5]):
                # 如果当前为写入模式，在新目录拷贝一份该文件
                if _type == WRITEIN:
                    copy(os.path.join(root, json_file), new_path)
                print(f'{json_file} 不在白名单内，已跳过！\n')
                continue

            deal_with_json_file(root, json_file, _type, new_path)


def deal_with_json_file(root: str, json_file: str, _type: str, new_path: str):
    '''
    处理JSON数据
    '''

    print(f'当前扫描文本：{json_file}')
    json_datas = read_json(os.path.join(root, json_file))
    try:
        if len(json_datas) < 1:
            print(f'{json_file} 无内容，已跳过！\n')
            return
    except Exception as e:
        if isinstance(json_datas, list) and len(json_datas) < 1:
            print(f'{json_file} 数据异常，已跳过！\n')
            return

    filename = json_file[:-5]
    # 翻译文本所在文件的标识
    file_mark = ''
    # 在处理文本之前，将标识行写入缓存
    if _type == EXTRACT:
        file_mark = f'{KEY_MARK1}{filename} {datetime.now(
        ).strftime('%Y_%m_%d %H:%M')}{KEY_MARK2}'
        write_in_cache(file_mark, '', '', file_mark)

    # 记录文本更改
    _change = False

    if filename in GLOBAL_DATA['rpg_type_array_object']:
        _change = sacnning_type_player(json_datas, _type, filename)
    elif filename == TYPE_COMMONEVENTS:
        _change = sacnning_common_events(json_datas, _type)
    elif filename == TYPE_SYSTEM:
        _change = scanning_system(json_datas, _type, filename)
    elif PATTERN_MAP.match(filename):
        _change = scanning_type_maps(json_datas, _type, filename)

    # 提取模式
    if _type == EXTRACT:
        # 如果数据无变动，删除之前写入的标识行
        if not _change:
            del_key_from_dict(_game_txt_cache, file_mark)
        print_info(f'{json_file} 扫描完成！\n')

    # 写入模式
    elif _type == WRITEIN:
        write_json(os.path.join(new_path, json_file), json_datas, 2)


def sacnning_type_player(json_datas: any, _type: str, filename: str) -> bool:
    '''
    扫描各种武器护具敌人等数据文件。数据结构：array -> object
    '''

    # 记录文本更改
    _change = False

    if not json_datas or not isinstance(json_datas, list):
        return _change

    for i_json_datas, item_json_datas in enumerate(json_datas):
        if not item_json_datas:
            continue

        if KEY_NAME in item_json_datas and isinstance(item_json_datas[KEY_NAME], str):
            # 人名、昵称基本不会出现歧义，可以去重
            if filename in GLOBAL_DATA['rpg_duplicate_removal_list']:
                if _type == EXTRACT:
                    _change = switch_change_mark(
                        _change, write_in_cache(item_json_datas[KEY_NAME])
                    )
                else:
                    json_datas[i_json_datas][KEY_NAME] = read_from_cache(
                        item_json_datas[KEY_NAME]
                    )
            else:
                _loc = get_md5('_'.join([filename, str(i_json_datas), KEY_NAME]), True)
                if _type == EXTRACT:
                    _change = switch_change_mark(
                        _change, write_in_cache(item_json_datas[KEY_NAME], _loc)
                    )
                else:
                    json_datas[i_json_datas][KEY_NAME] = read_from_cache(
                        item_json_datas[KEY_NAME], _loc
                    )

        if KEY_NICKNAME in item_json_datas and isinstance(
            item_json_datas[KEY_NICKNAME], str
        ):
            if _type == EXTRACT:
                _change = switch_change_mark(
                    _change, write_in_cache(item_json_datas[KEY_NICKNAME])
                )
            else:
                json_datas[i_json_datas][KEY_NICKNAME] = read_from_cache(
                    item_json_datas[KEY_NICKNAME]
                )

        if KEY_DESCRIPTION in item_json_datas and isinstance(
            item_json_datas[KEY_DESCRIPTION], str
        ):
            if _type == EXTRACT:
                _change = switch_change_mark(
                    _change, write_in_cache(item_json_datas[KEY_DESCRIPTION])
                )
            else:
                json_datas[i_json_datas][KEY_DESCRIPTION] = read_from_cache(
                    item_json_datas[KEY_DESCRIPTION]
                )

        if KEY_MESSAGE1 in item_json_datas and isinstance(
            item_json_datas[KEY_MESSAGE1], str
        ):
            if _type == EXTRACT:
                _change = switch_change_mark(
                    _change, write_in_cache(item_json_datas[KEY_MESSAGE1])
                )
            else:
                json_datas[i_json_datas][KEY_MESSAGE1] = read_from_cache(
                    item_json_datas[KEY_MESSAGE1]
                )

        if KEY_MESSAGE2 in item_json_datas and isinstance(
            item_json_datas[KEY_MESSAGE2], str
        ):
            if _type == EXTRACT:
                _change = switch_change_mark(
                    _change, write_in_cache(item_json_datas[KEY_MESSAGE2])
                )
            else:
                json_datas[i_json_datas][KEY_MESSAGE2] = read_from_cache(
                    item_json_datas[KEY_MESSAGE2]
                )

        if KEY_MESSAGE3 in item_json_datas and isinstance(
            item_json_datas[KEY_MESSAGE3], str
        ):
            if _type == EXTRACT:
                _change = switch_change_mark(
                    _change, write_in_cache(item_json_datas[KEY_MESSAGE3])
                )
            else:
                json_datas[i_json_datas][KEY_MESSAGE3] = read_from_cache(
                    item_json_datas[KEY_MESSAGE3]
                )

        if KEY_MESSAGE4 in item_json_datas and isinstance(
            item_json_datas[KEY_MESSAGE4], str
        ):
            if _type == EXTRACT:
                _change = switch_change_mark(
                    _change, write_in_cache(item_json_datas[KEY_MESSAGE4])
                )
            else:
                json_datas[i_json_datas][KEY_MESSAGE4] = read_from_cache(
                    item_json_datas[KEY_MESSAGE4]
                )

        if (
            KEY_PAGES in item_json_datas
            and isinstance(item_json_datas[KEY_PAGES], list)
            and len(item_json_datas[KEY_PAGES]) > 0
        ):
            pages = item_json_datas[KEY_PAGES]
            for i_pages, item_pages in enumerate(pages):
                if (
                    not KEY_LIST in item_pages
                    or not isinstance(item_pages[KEY_LIST], list)
                    or len(item_pages[KEY_LIST]) < 1
                ):
                    continue

                lists = item_pages[KEY_LIST]
                # 记录各元素的索引位置，用于删除无用的文本行
                idx_list = []
                for i_lists, item_lists in enumerate(lists):
                    if not item_lists:
                        continue

                    parameters = item_lists[KEY_PARAMETERS]
                    if not isinstance(parameters, list) or len(parameters) < 1:
                        continue

                    code = item_lists[KEY_CODE]
                    # 选择菜单
                    if (
                        code == 102
                        and isinstance(parameters[0], list)
                        and len(parameters[0]) > 0
                    ):
                        for i, item in enumerate(parameters[0]):
                            if _type == EXTRACT:
                                _change = switch_change_mark(
                                    _change, write_in_cache(item)
                                )
                            else:
                                lists[i_lists][KEY_PARAMETERS][0][i] = read_from_cache(
                                    item
                                )
                        continue

                    # 改名
                    if code == 320 and isinstance(parameters[1], str):
                        if _type == EXTRACT:
                            _change = switch_change_mark(
                                _change, write_in_cache(parameters[1])
                            )
                        else:
                            lists[i_lists][KEY_PARAMETERS][1] = read_from_cache(
                                parameters[1]
                            )
                        continue

                    # 脚本
                    if code in [355, 655] and isinstance(parameters[0], str):
                        if '"' not in parameters[0]:
                            continue
                        if _type == EXTRACT:
                            _change = switch_change_mark(
                                _change,
                                write_in_cache(parameters[0], value=parameters[0]),
                            )
                        else:
                            txt = read_from_cache(parameters[0])
                            if txt.strip().upper() == NONE_MARK:
                                idx_list.append(i_lists)
                                txt = ''
                            lists[i_lists][KEY_PARAMETERS][0] = txt

                    # 对话
                    if code == 401 and isinstance(parameters[0], str):
                        if _type == EXTRACT:
                            _change = switch_change_mark(
                                _change, write_in_cache(parameters[0])
                            )
                        else:
                            txt = read_from_cache(parameters[0])
                            if txt.strip().upper() == NONE_MARK:
                                idx_list.append(i_lists)
                                txt = ''
                            lists[i_lists][KEY_PARAMETERS][0] = txt
                        continue

                    # 选项
                    if code == 402 and isinstance(parameters[1], str):
                        if _type == EXTRACT:
                            _change = switch_change_mark(
                                _change, write_in_cache(parameters[1])
                            )
                        else:
                            lists[i_lists][KEY_PARAMETERS][1] = read_from_cache(
                                parameters[1]
                            )
                        continue

                    # 滚动文章
                    if code == 405 and isinstance(parameters[0], str):
                        if _type == EXTRACT:
                            _change = switch_change_mark(
                                _change, write_in_cache(parameters[0])
                            )
                        else:
                            txt = read_from_cache(parameters[0])
                            if txt.strip().upper() == NONE_MARK:
                                idx_list.append(i_lists)
                                txt = ''
                            lists[i_lists][KEY_PARAMETERS][0] = txt
                        continue

                if len(idx_list) > 0:
                    # 反向列表中元素
                    idx_list.reverse()
                    # 统一删除空文本行
                    for v in idx_list:
                        lists.pop(v)
                pages[i_pages][KEY_LIST] = lists
            json_datas[i_json_datas][KEY_PAGES] = pages

    return _change


def sacnning_common_events(json_datas: any, _type: str) -> bool:
    '''
    扫描CommonEvents.json
    '''

    # 记录文本更改
    _change = False

    if not json_datas or not isinstance(json_datas, list) or len(json_datas) < 1:
        return _change

    for i_json_datas, item_json_datas in enumerate(json_datas):
        if not item_json_datas:
            continue

        if (
            not KEY_LIST in item_json_datas
            or not isinstance(item_json_datas[KEY_LIST], list)
            or len(item_json_datas[KEY_LIST]) < 1
        ):
            continue

        lists = item_json_datas[KEY_LIST]
        # 记录各元素的索引位置，用于删除无用的文本行
        idx_list = []
        for i_lists, item_lists in enumerate(lists):
            if not item_lists:
                continue

            parameters = item_lists[KEY_PARAMETERS]
            if not isinstance(parameters, list) or len(parameters) < 1:
                continue

            code = item_lists[KEY_CODE]
            # 选择菜单
            if (
                code == 102
                and isinstance(parameters[0], list)
                and len(parameters[0]) > 0
            ):
                for i, item in enumerate(parameters[0]):
                    if _type == EXTRACT:
                        _change = switch_change_mark(_change, write_in_cache(item))
                    else:
                        lists[i_lists][KEY_PARAMETERS][0][i] = read_from_cache(item)
                continue

            # 改名
            if code == 320 and isinstance(parameters[1], str):
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(parameters[1]))
                else:
                    lists[i_lists][KEY_PARAMETERS][1] = read_from_cache(parameters[1])
                continue

            # 脚本
            if code in [355, 655] and isinstance(parameters[0], str):
                if '"' not in parameters[0]:
                    continue
                if _type == EXTRACT:
                    _change = switch_change_mark(
                        _change, write_in_cache(parameters[0], value=parameters[0])
                    )
                else:
                    txt = read_from_cache(parameters[0])
                    if txt.strip().upper() == NONE_MARK:
                        idx_list.append(i_lists)
                        txt = ''
                    lists[i_lists][KEY_PARAMETERS][0] = txt

            # 对话
            if code == 401 and isinstance(parameters[0], str):
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(parameters[0]))
                else:
                    txt = read_from_cache(parameters[0])
                    if txt.strip().upper() == NONE_MARK:
                        idx_list.append(i_lists)
                        txt = ''
                    lists[i_lists][KEY_PARAMETERS][0] = txt
                continue

            # 选项
            if code == 402 and isinstance(parameters[1], str):
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(parameters[1]))
                else:
                    lists[i_lists][KEY_PARAMETERS][1] = read_from_cache(parameters[1])
                continue

            # 滚动文章
            if code == 405 and isinstance(parameters[0], str):
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(parameters[0]))
                else:
                    txt = read_from_cache(parameters[0])
                    if txt.strip().upper() == NONE_MARK:
                        idx_list.append(i_lists)
                        txt = ''
                    lists[i_lists][KEY_PARAMETERS][0] = txt
                continue

        if len(idx_list) > 0:
            # 反向列表中元素
            idx_list.reverse()
            # 统一删除空文本行
            for v in idx_list:
                lists.pop(v)
        json_datas[i_json_datas][KEY_LIST] = lists

    return _change


def scanning_system(json_datas: any, _type: str, filename: str):
    '''
    扫描System.json
    '''

    # 记录文本更改
    _change = False

    if not json_datas or not isinstance(json_datas, dict):
        return _change

    if (
        KEY_ELEMENTS in json_datas
        and isinstance(json_datas[KEY_ELEMENTS], list)
        and len(json_datas[KEY_ELEMENTS]) > 0
    ):
        for i, item in enumerate(json_datas[KEY_ELEMENTS]):
            _loc = get_md5('_'.join([filename, KEY_ELEMENTS, str(i)]), True)
            if _type == EXTRACT:
                _change = switch_change_mark(_change, write_in_cache(item, _loc))
            else:
                json_datas[KEY_ELEMENTS][i] = read_from_cache(item, _loc)

    if KEY_TERMS in json_datas:
        _terms = json_datas[KEY_TERMS]
        if (
            KEY_PARAMS in _terms
            and isinstance(_terms[KEY_PARAMS], list)
            and len(_terms[KEY_PARAMS]) > 0
        ):
            for i, item in enumerate(_terms[KEY_PARAMS]):
                _loc = get_md5(
                    '_'.join([filename, KEY_TERMS, KEY_PARAMS, str(i)]), True
                )
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(item, _loc))
                else:
                    json_datas[KEY_TERMS][KEY_PARAMS][i] = read_from_cache(item, _loc)

        if (
            KEY_ETYPES in _terms
            and isinstance(_terms[KEY_ETYPES], list)
            and len(_terms[KEY_ETYPES]) > 0
        ):
            for i, item in enumerate(_terms[KEY_ETYPES]):
                _loc = get_md5(
                    '_'.join([filename, KEY_TERMS, KEY_ETYPES, str(i)]), True
                )
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(item, _loc))
                else:
                    json_datas[KEY_TERMS][KEY_ETYPES][i] = read_from_cache(item, _loc)

        if (
            KEY_COMMANDS in _terms
            and isinstance(_terms[KEY_COMMANDS], list)
            and len(_terms[KEY_COMMANDS]) > 0
        ):
            for i, item in enumerate(_terms[KEY_COMMANDS]):
                _loc = get_md5(
                    '_'.join([filename, KEY_TERMS, KEY_COMMANDS, str(i)]), True
                )
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(item, _loc))
                else:
                    json_datas[KEY_TERMS][KEY_COMMANDS][i] = read_from_cache(item, _loc)

        if (
            KEY_BASIC in _terms
            and isinstance(_terms[KEY_BASIC], list)
            and len(_terms[KEY_BASIC]) > 0
        ):
            for i, item in enumerate(_terms[KEY_BASIC]):
                _loc = get_md5('_'.join([filename, KEY_TERMS, KEY_BASIC, str(i)]), True)
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(item, _loc))
                else:
                    json_datas[KEY_TERMS][KEY_BASIC][i] = read_from_cache(item, _loc)

        if (
            KEY_SKILL_TYPES in json_datas
            and isinstance(json_datas[KEY_SKILL_TYPES], list)
            and len(json_datas[KEY_SKILL_TYPES]) > 0
        ):
            for i, item in enumerate(json_datas[KEY_SKILL_TYPES]):
                _loc = get_md5('_'.join([filename, KEY_SKILL_TYPES, str(i)]), True)
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(item, _loc))
                else:
                    json_datas[KEY_SKILL_TYPES][i] = read_from_cache(item, _loc)

        if (
            KEY_WEAPON_TYPES in json_datas
            and isinstance(json_datas[KEY_WEAPON_TYPES], list)
            and len(json_datas[KEY_WEAPON_TYPES]) > 0
        ):
            for i, item in enumerate(json_datas[KEY_WEAPON_TYPES]):
                _loc = get_md5('_'.join([filename, KEY_WEAPON_TYPES, str(i)]), True)
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(item, _loc))
                else:
                    json_datas[KEY_WEAPON_TYPES][i] = read_from_cache(item, _loc)

        if (
            KEY_ARMOR_TYPES in json_datas
            and isinstance(json_datas[KEY_ARMOR_TYPES], list)
            and len(json_datas[KEY_ARMOR_TYPES]) > 0
        ):
            for i, item in enumerate(json_datas[KEY_ARMOR_TYPES]):
                _loc = get_md5('_'.join([filename, KEY_ARMOR_TYPES, str(i)]), True)
                if _type == EXTRACT:
                    _change = switch_change_mark(_change, write_in_cache(item, _loc))
                else:
                    json_datas[KEY_ARMOR_TYPES][i] = read_from_cache(item, _loc)

        if KEY_CURRENCY_UNIT in json_datas and isinstance(
            json_datas[KEY_CURRENCY_UNIT], str
        ):
            _loc = get_md5('_'.join([filename, KEY_CURRENCY_UNIT]), True)
            if _type == EXTRACT:
                _change = switch_change_mark(
                    _change, write_in_cache(json_datas[KEY_CURRENCY_UNIT], _loc)
                )
            else:
                json_datas[KEY_CURRENCY_UNIT] = read_from_cache(
                    json_datas[KEY_CURRENCY_UNIT], _loc
                )

    return _change


def scanning_type_maps(json_datas: any, _type: str, filename: str) -> bool:
    '''
    扫描各种Map
    '''

    # 记录文本更改
    _change = False

    if not json_datas or not isinstance(json_datas, dict):
        return _change

    if KEY_DISPLAY_NAME in json_datas and isinstance(json_datas[KEY_DISPLAY_NAME], str):
        _loc = get_md5('_'.join([filename, KEY_DISPLAY_NAME]), True)
        if _type == EXTRACT:
            _change = switch_change_mark(
                _change, write_in_cache(json_datas[KEY_DISPLAY_NAME], _loc)
            )
        else:
            json_datas[KEY_DISPLAY_NAME] = read_from_cache(
                json_datas[KEY_DISPLAY_NAME], _loc
            )

    if not KEY_EVENTS in json_datas or not isinstance(json_datas[KEY_EVENTS], dict):
        return _change

    for i_events, item_events in json_datas[KEY_EVENTS].items():
        if not KEY_PAGES in item_events:
            continue

        pages = item_events[KEY_PAGES]
        if not isinstance(pages, list) or len(pages) < 1:
            continue

        for i_pages, item_pages in enumerate(pages):
            if (
                not KEY_LIST in item_pages
                or not isinstance(item_pages[KEY_LIST], list)
                or len(item_pages[KEY_LIST]) < 1
            ):
                continue

            lists = item_pages[KEY_LIST]
            # 记录各元素的索引位置，用于删除无用的文本行
            idx_list = []
            for i_lists, item_lists in enumerate(lists):
                if not item_lists:
                    continue

                parameters = item_lists[KEY_PARAMETERS]
                if not isinstance(parameters, list) or len(parameters) < 1:
                    continue

                code = item_lists[KEY_CODE]
                # 选择菜单
                if (
                    code == 102
                    and isinstance(parameters[0], list)
                    and len(parameters[0]) > 0
                ):
                    for i, item in enumerate(parameters[0]):
                        if _type == EXTRACT:
                            
                            _change = switch_change_mark(_change, write_in_cache(item))
                        else:
                            lists[i_lists][KEY_PARAMETERS][0][i] = read_from_cache(item)
                    continue

                # 改名
                if code == 320 and isinstance(parameters[1], str):
                    if _type == EXTRACT:
                        _change = switch_change_mark(
                            _change, write_in_cache(parameters[1])
                        )
                    else:
                        lists[i_lists][KEY_PARAMETERS][1] = read_from_cache(
                            parameters[1]
                        )
                    continue

                # 脚本
                if code in [355, 655] and isinstance(parameters[0], str):
                    if '"' not in parameters[0]:
                        continue
                    if _type == EXTRACT:
                        _change = switch_change_mark(
                            _change, write_in_cache(parameters[0], value=parameters[0])
                        )
                    else:
                        txt = read_from_cache(parameters[0])
                        if txt.strip().upper() == NONE_MARK:
                            idx_list.append(i_lists)
                            txt = ''
                        lists[i_lists][KEY_PARAMETERS][0] = txt

                # 对话
                if code == 401 and isinstance(parameters[0], str):
                    if _type == EXTRACT:
                        _change = switch_change_mark(
                            _change, write_in_cache(parameters[0])
                        )
                    else:
                        txt = read_from_cache(parameters[0])
                        if txt.strip().upper() == NONE_MARK:
                            idx_list.append(i_lists)
                            txt = ''
                        lists[i_lists][KEY_PARAMETERS][0] = txt
                    continue

                # 选项
                if code == 402 and isinstance(parameters[1], str):
                    if _type == EXTRACT:
                        _change = switch_change_mark(
                            _change, write_in_cache(parameters[1])
                        )
                    else:
                        lists[i_lists][KEY_PARAMETERS][1] = read_from_cache(
                            parameters[1]
                        )
                    continue

                # 滚动文章
                if code == 405 and isinstance(parameters[0], str):
                    if _type == EXTRACT:
                        _change = switch_change_mark(
                            _change, write_in_cache(parameters[0])
                        )
                    else:
                        txt = read_from_cache(parameters[0])
                        if txt.strip().upper() == NONE_MARK:
                            idx_list.append(i_lists)
                            txt = ''
                        lists[i_lists][KEY_PARAMETERS][0] = txt
                    continue

            if len(idx_list) > 0:
                # 反向列表中元素
                idx_list.reverse()
                # 统一删除空文本行
                for v in idx_list:
                    lists.pop(v)
            pages[i_pages][KEY_LIST] = lists
        json_datas[KEY_EVENTS][i_events][KEY_PAGES] = pages

    return _change


def _read_game_txt(_type: str) -> bool:
    '''
    读取gameText.json和文本库
    '''

    # 读取翻译文本，写入缓存
    global _game_txt_cache
    _game_txt_cache = read_json(os.path.join(BASE_ABSPATH, RPGM_GAME_TXT))

    # 将更新标识的值重置为False
    change_phoenix_mark(_game_txt_cache)

    # 当处于写入模式时，如果缓存数据为空，则返回False
    if _type == WRITEIN and len(_game_txt_cache) < 2:
        print_err(f'{RPGM_GAME_TXT} 不存在或无内容！')
        return False

    # 读取引擎默认文本库
    default_libraries = read_json(
        os.path.join(BASE_ABSPATH, 'libraries', RPGVXACE_DEFAULT_LIBRARY)
    )
    # 读取译文库
    translated_libraries = read_json(
        os.path.join(BASE_ABSPATH, 'libraries', RPGM_BAK_GAME_TXT)
    )
    # 初始化译文库缓存
    global _game_txt_library
    _game_txt_library = merge_dict(default_libraries, translated_libraries)

    return True


def write_in_cache(key: str, _loc='', _filter='', value='') -> bool:
    '''
    将数据存入缓存
    '''

    if not key or key.strip() == '':
        return False

    _key = _loc + '_' + key if _loc != '' else key

    # 不匹配指定语种的文本不存入缓存
    if not matching_langs(key, _filter):
        return False

    # 缓存中已有该字段，且值不为空字串或TODO时，直接返回
    if (
        _key in _game_txt_cache
        and _game_txt_cache[_key] != ''
        and _game_txt_cache[_key].strip().upper() != TODO_MARK
    ):
        return False

    # default_strings中有该条文本且不为空字串，赋值
    if (
        _key in _game_txt_library
        and _game_txt_library[_key] != ''
        and _game_txt_library[_key].strip().upper() != TODO_MARK
    ):
        _game_txt_cache[_key] = _game_txt_library[_key]
        change_phoenix_mark(_game_txt_cache, True)
        return True

    # 如果参数中直接传入了文本值value且不为空字符串时，直接赋值
    if value != '':
        _game_txt_cache[_key] = value
        if _key.startswith(KEY_MARK1) and _key.endswith(KEY_MARK2):
            return True
        change_phoenix_mark(_game_txt_cache, True)
        return True

    # 既然前面可赋值的情况都pass了，若缓存中有该字段，直接返回
    if _key in _game_txt_cache:
        return False

    _game_txt_cache[_key] = ''
    change_phoenix_mark(_game_txt_cache, True)
    return True


def read_from_cache(key: str, _loc='') -> str:
    '''
    从缓存获取数据
    '''

    if not key or key.strip() == '':
        return key

    _key = _loc + '_' + key if _loc != '' else key

    if not _key in _game_txt_cache or _game_txt_cache[_key] == '':
        return key
    # if TODO_FILTER in _game_txt_cache[_key].upper():    # 标记。待复核文本
    #     return key
    if _game_txt_cache[_key].strip().upper() == TODO_MARK:  # 标记。待翻译文本
        return key
    if _game_txt_cache[_key].upper() in GLOBAL_DATA['pass_filter']:  # 标记。不翻译文本
        return key

    return _game_txt_cache[_key]


def _select_serial_num(reselect=False, serial_num=''):
    '''
    输入序号选择对应的操作
    '''

    if not reselect:
        print(
            '''1) 提取翻译文本
2) 写入翻译文本
0) 返回上一级
'''
        )

        _inp = input('请输入要操作的序号：').strip()
        if _inp == '1':
            walk_file(EXTRACT)
        elif _inp == '2':
            walk_file(WRITEIN)
        elif _inp == '0':
            main.start_main()
        else:
            _select_serial_num(True, _inp)
        return

    _tmp = input(
        f'列表中不存在序号 {serial_num}，请重新输入正确序号或回车退出程序：'
    ).strip()
    if _tmp == '':
        exit(0)

    if _tmp == '1':
        walk_file(EXTRACT)
    elif _tmp == '2':
        walk_file(WRITEIN)
    elif _tmp == '0':
        main.start_main()
    else:
        _select_serial_num(True, _tmp)


def start():
    '''
    启动界面
    '''

    print(
        '''
======================================================================
                    RPG Maker VX Ace 文本提取写入工具
                            作者：Phoenix
                            版权归作者所有
======================================================================
'''
    )

    _select_serial_num()

    # 判断翻译文本是否有变动，没有则跳过
    if KEY_PHOENIX in _game_txt_cache and not _game_txt_cache[KEY_PHOENIX]:
        print(f'{RPGM_GAME_TXT} 未发生更改，无需写入！\n')
        exit(0)

    # 将更新标识的值重置为False
    change_phoenix_mark(_game_txt_cache)
    # 更新gameText.json
    write_json(os.path.join(BASE_ABSPATH, RPGM_GAME_TXT), _game_txt_cache, 2, True)

    exit(0)
